remove_action not working with procedural function

The issue here is that the child theme functions.php is loaded before the parent theme functions.php. Therefore, the ordering of the add/remove actions would be something like so:

//* From the child theme
remove_action( 'wp_head', 'func', 5 );
//* From the parent theme
add_action( 'wp_head', 'func', 5 );

The callback to func on the wp_head hook is removed before it’s added. Therefore, it will appear that the child theme removing the action doesn’t work. In reality, the remove_action() function is attempting to remove the func callback from the wp_head hook, but it hasn’t been added yet.

The solution is to hook into WordPress anytime after the parent theme functions.php loads and then remove the action.

add_action( 'after_setup_theme', 'wpse_222809_after_setup_theme' );
function wpse_222809_after_setup_theme() {
  remove_action( 'wp_head', 'func', 5 );
}

This works because the after_setup_theme hook fires after the parent theme functions.php, so the ordering of the add/remove actions would thus be:

//* From the child theme
add_action( 'after_setup_theme', 'wpse_222809_after_setup_theme' );
//* From the parent theme
add_action( 'wp_head', 'func', 5 );
//* From the wpse_222809_after_setup_theme function hooked to after_setup_theme 
//*( hook added in child theme )
remove_action( 'wp_head', 'func', 5 );

This would also work with replacing after_setup_theme with init, as you figured out, because the init hook is fired after the parent theme functions.php and before wp_head.