Counting pending bookings using a subselect
Yes, there is a way to eliminate the repeated function call, but as to whether or not it would improve performance you need to benchmark it. This method writes the resulting data into a temporary table, which means it will call the function only once when populating it, but in turn will mean that it will have to write the table to tempdb for that session. Here is how it could be written that way:
if object_id('tempdb..#SpecialBookings') is not null
    drop table tempdb..#SpecialBookings;

select *
into #SpecialBookings
from SPECIAL_GROUP as grp
    cross apply f_BookingsForSpecialGroup(grp.SPECIAL_GROUP_ID) as bookings
where (bookings.IS_BAD = 0 or bookings.IS_PAID = 1);

select (grpCounted.NON_BAD_BOOKINGS - grpCounted.PAID_BOOKINGS) as PENDING_BOOKINGS, * 
from 
(
    select
        (select count(*) from #SpecialBookings where IS_BAD=0) as NON_BAD_BOOKINGS,
        (select count(*) from #SpecialBookings where IS_PAID=1) as PAID_BOOKINGS,
        *
    from #SpecialBookings
) as grpCounted;

if object_id('tempdb..#SpecialBookings') is not null
    drop table tempdb..#SpecialBookings;


select *
Do you really need all the fields from both the SPECIAL_GROUP table and the f_BookingsForSpecialGroup? If you do really need them, then fair enough, but otherwise, you should not use select *.

Aliases
As you can see I renamed your table aliases a bit to make your code easier to read. Whenever possible, avoid single-letter or otherwise meaningless aliases as they make the code less clear.