Conversion from unsigned int to either int or float results in a loss of precision, and both are considered equal by the compiler. You have to add an explicit case to make the compiler decide which to use, e.g.:
foo(i, static_cast<float>(f));
Note that there is no such thing as unsigned float. If the compiler accepts that, it is not standards-compliant (VC2010 warns about it, not sure about VC2005).
The relevant sections of the C++98 standard are section 4, which ranks a numeric type cast as either an exact match, a promotion, or a conversion, and section 13.3.3.2, which defines how implicit conversions are ranked for overload resolution. The latter section states, in subparagraph 4:
Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion, which is a better conversion than a Conversion.
Conversion from unsigned int to either float or int is ranked as "Conversion" either way, so it is "indistinguishable", making the overload ambiguous.
Since unsigned float is not an actual type according to the standard, it's hard to say how this applies in your situation, but your compiler appears to treat conversion from unsigned float to either float or int as indistinguishable too.