I know that's the case for ints, but in this case [0] the int was cast to a boolean, which I thought would ensure comparisons would perform as expected, but no such luck.
In this case the expression has type bool and the underlying object has type int, so it is a straightforward strict aliasing violation.
With GCC you can compile with -fno-strict-aliasing to ignore this rule. But now you fall afoul of the rule that prevents accessing an invalid representation (i.e. a trap-representation) of an object. This rule is also described in the link I posted before, under the object representation paragraph.
Even ignoring both rules, there is still no reason to expect the assertion not to fire:
int x = 2;
assert(*(bool*)x == true);
This is the same as: float x = 2.0
assert(*(int*)x == 2);
Just because two object are convertible, there is no reason to expect their representation to be the same.