If the "OR in a byte then shift, repeat" thing didn't work, it may be an "endian" issue. In short, the order of the bytes was backwards.
Debugging: Can you set the IMU on its side (or whatever) so it will send you a 1G accelleration signal on Y axis and a 0G accelleration signal on the X axis? On the Arduino, you need to print out / send back to the PC (in ASCII) the bytes in the order they are received. You will need to hand code the proper floating point value for 0 and 1 and be able to recognise small (noise) variations.
This will give you a clue as to what order the bytes are coming in. They may be completely backwards, or just the pairs backwards. OTOH, if that is OK, then post your "oring in and shifting" code for us to look for errors.
A generic union is accessed like this:
union u_tag {
int ival;
float fval;
} u;
u.ival = 14;
u.fval = 31.3;
yours might look like:
float velocity;
union u_tag {
byte b[4];
float fval;
} u;
u.b[0] = ...
u.b[1] = ...
u.b[3] = ...
u.b[3] = ...
velocity = u.fval;
It might compile.

Here is some code reading out the float value a byte at a time. It compiles and runs. 8-)
void setup()
{
Serial.begin(9600);
// prints title with ending line break
Serial.println("Floats coming out as bytes!!");
// wait for the long string to be sent
delay(100);
}
float myVelocity = 0.0;
union u_tag {
byte b[4];
float fval;
} u;
void loop()
{
u.fval = myVelocity;
Serial.print("Byte 1: ");
Serial.println(u.b[0], DEC );
Serial.print("Byte 2: ");
Serial.println(u.b[1], DEC );
Serial.print("Byte 3: ");
Serial.println(u.b[2], DEC );
Serial.print("Byte 4: ");
Serial.println(u.b[3], DEC );
Serial.println();
myVelocity += 1.0;
delay(100); // allow some time for the Serial data to be sent
}