Ideally, you want to fix the client code so it doesn't throw away type information in the first place. Or, if you can't do that, you at least want to know what the rule is for how these strings are generated, so you can work out how to reverse the rule.
But if neither of those is possible, and you need to guess, one possibility is something like this:
def parseval(s): try: return int(s) except ValueError: pass try: return float(s) except ValueError: pass return s
This will treat anything that could be a valid int as an int, anything that can't be a valid int but could be a valid float as a float, and anything else as a str.
In the special case where the output comes from just calling repr or str in Python, you may want this:
import ast def parseval(s): try: return ast.literal_eval(s) except ValueError: return s
This will convert any Python literal, or any collection display made up of literals and other collection displays made up of etc. recursively, to the original value, but leave anything else as itself. (If you know the client is using repr rather than str, you should leave off the try/except. But if it's using str, this works, because it relies on the fact that, for every kind of literal but strings, the str is interpretable as a repr.)
However, note that this makes it impossible to, e.g., send the string "10" to your server.