Add first letter of titles to array, then compare arrays

The arguments for in_array() are the wrong way round. Looking at the documentation you can see that the first argument is the value you want to check (the ‘needle’) and the second argument is the array you want to check for it in (the ‘haystack’).

So this means it’s always evaluating as false, meaning that the code inside the condition is running every time.

Just swap the arguments around to fix the issue:

if( ! in_array( $title_alpha, $post_alphas ) ) {
    $post_alphas[] = $title_alpha;
}

There’s a (I think) cleaner way to do this though, with a bit less code. You can get the posts first, then use array_map() to replace every value in the array with just the first letter of each title. Then finally array_unique() to remove duplicates:

$posts = get_posts( array(
    'post_type'      => 'foundation_firms',
    'post_status'    => 'publish',
    'order'          => 'ASC',
    'posts_per_page' => -1,
    'orderby'        => 'title',
) );

$letters = array_map( $posts, function( $post ) {
    return $post->post_title[0];
} );

$letters_unique = array_unique( $letters );